package com.heima.comment.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.heima.comment.feign.UserFeign;
import com.heima.comment.service.CommentService;
import com.heima.common.aliyun.GreeTextScan;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.utils.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
@Transactional
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    UserFeign userFeign;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private GreeTextScan greeTextScan;

    @Resource(name="likesLock")
    RLock rLock;

    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //检查参数
        if (dto == null || dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if (dto.getContent().length() > 140 || dto.getContent() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        ApUser user = AppThreadLocalUtils.getUser();

        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        try {
            Map map = greeTextScan.greeTextScan(dto.getContent());
            String suggestion = (String) map.get("suggestion");
            if ("block".equals(suggestion)) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论有违规，请注意你的言辞");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "内容审核出现异常");
        }
        ApUser userById = userFeign.findUserById(Long.valueOf(user.getId()));
        ApComment apComment = new ApComment();
        apComment.setAuthorId(userById.getId());
        apComment.setAuthorName(userById.getName());
        apComment.setEntryId(dto.getArticleId());
        apComment.setContent(dto.getContent());
        apComment.setImage(userById.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short) 0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        mongoTemplate.save(apComment);


        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //检查参数
        if (dto == null || dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);

        }
        if (dto.getOperation() == null || (dto.getOperation() != 0 && dto.getOperation() != 1)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        ApUser user = AppThreadLocalUtils.getUser();

        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        rLock.lock();
        ApComment apComment;
        try {
            apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (apComment == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "该评论不存在");
            }
            if (dto.getOperation() == 0) {
                apComment.setLikes(apComment.getLikes() + 1);
                mongoTemplate.save(apComment);

                ApCommentLike apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(user.getId());
                apCommentLike.setCommentId(dto.getCommentId());
                apCommentLike.setOperation((short) 0);
                mongoTemplate.save(apCommentLike);

            }
            if (dto.getOperation() == 1) {
                apComment.setLikes(apComment.getLikes() == 0 ? 0 : apComment.getLikes() - 1);
                mongoTemplate.save(apComment);

                Query query = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId()));

                mongoTemplate.remove(query,ApCommentLike.class);
            }
        } finally {
            rLock.unlock();
        }
        Map map = new HashMap();
        map.put("likes",apComment.getLikes());
        return ResponseResult.okResult(map);
    }

    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //判断参数
        if (dto==null||dto.getArticleId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        if (dto.getMinDate()==null){
            dto.setMinDate(new Date());
        }
        ApUser user = AppThreadLocalUtils.getUser();
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                .and("createdTime").lt(dto.getMinDate()))
                .with(Sort.by(Sort.Direction.DESC,"createdTime")).limit(20);
        List<ApComment> apComments = mongoTemplate.find(query, ApComment.class);

        if (user==null){
            return ResponseResult.okResult(apComments);
        }
        List<String> ids = apComments.stream().map(ApComment::getId).collect(Collectors.toList());
        Query queryLike = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").in(ids));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(queryLike, ApCommentLike.class);
        List<String> collect = apCommentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());


        List<ApCommentVo> apCommentVos = apComments.stream().map(apComment -> {
                    ApCommentVo apCommentVo = new ApCommentVo();
                    BeanUtils.copyProperties(apComment, apCommentVo);
                    if (collect.contains(apComment.getId())) {
                        apCommentVo.setOperation((short) 0);

                    }
                    return apCommentVo;
                }

        ).collect(Collectors.toList());


        return ResponseResult.okResult(apCommentVos);
    }
}
